package com.gosophia.dataDictionary.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.gosophia.commons.OrderCondition;
import com.gosophia.commons.Page;
import com.gosophia.commons.exception.BusinessException;
import com.gosophia.commons.exception.ConcurrencyException;
import com.gosophia.commons.exception.ExceptionDetail;
import com.gosophia.dataDictionary.dao.DataEntryDAO;
import com.gosophia.dataDictionary.dao.DataValueDAO;
import com.gosophia.dataDictionary.entity.DataEntry;
import com.gosophia.dataDictionary.entity.DataValue;
import com.gosophia.dataDictionary.service.DataDictionaryService;

/**
 * 数据字典service实现
 * 
 * @author tianchunyu
 * @date 2010-8-9
 */
@Transactional
@Service("dataDictionaryService")
public class DataDictionaryServiceImpl implements DataDictionaryService {

    @Autowired
    private DataEntryDAO dataEntryDAO;

    @Autowired
    private DataValueDAO dataValueDAO;

    /**
     * 模糊查询所有符合条件的词条集合（分页）
     * 
     * @param pageNo
     *            返回数据的页码 必须大于0
     * @param pageSize
     *            每页数据行数 必须大于0
     * @param propertyFilters
     *            查询条件集合
     * @param orderConditions
     *            排序方式集合
     * @return 返回符合分页条件的所有词条集合
     */
    @Override
    public Page<DataEntry> findDataEntriesByPage(int pageNo, int pageSize,
            String searchCon, List<OrderCondition> orderConditions) {
        Assert.isTrue(pageSize > 0, "pageSize必须大于0");
        Assert.isTrue(pageNo > 0, "pageNo必须大于0");
        Page<DataEntry> page = new Page<DataEntry>();
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);
        if(orderConditions==null||orderConditions.isEmpty()){
            orderConditions = new ArrayList<OrderCondition>();
            OrderCondition oc = OrderCondition.asc("entryNameCN");
            orderConditions.add(oc);
        }
        return dataEntryDAO.getPageBySimpleSearching(page, searchCon,
                orderConditions);
    }

    /**
     * 根据entryId查找Entry实体
     * 
     * @param entryId不能为null
     * @return 根据entryId查到的Entry实体
     * @throws 当对象不存在时，抛出ConcurrencyException
     */
    @Override
    public DataEntry findDataEntryById(Long dataEntryId) {
        Assert.notNull(dataEntryId, "dataEntryId不能为null");
        DataEntry dataEntry = dataEntryDAO.get(dataEntryId);
        if (dataEntry != null) {
            List<DataValue> dataValues = dataEntry.getDataValues();
            if (dataValues != null && dataValues.size() != 0) {
                lineUpDataValue(dataValues);
                dataEntry.setDataValues(dataValues);
            }
            return dataEntry;
        }else{
            throw new ConcurrencyException("该对象不存在，请刷新最新数据。", "JC_DD_C_1");
        }
       
    }

    /**
     * 根据数据值id查找对应的数据值
     * 
     * @param dataValueId
     *            不能为null
     * @return 返回数据值id对应的数据值
     * @throws 当对象不存在时，抛出ConcurrencyException
     */
    @Override
    public DataValue findDataValueByDataValueId(Long dataValueId)
            throws ConcurrencyException {
        Assert.notNull(dataValueId, "dataValueId不能为null");
        DataValue dataValue = dataValueDAO.get(dataValueId);
        if (dataValue == null) {
            throw new ConcurrencyException("该对象不存在，请刷新最新数据。", "JC_DD_C_1");
        }
        return dataValue;
    }

    /**
     * 根据词条Id返回启用的数据值集合
     * 
     * @param entryId
     *            不能为null
     * @return 返回根据词条Id查找的启用数据值集合（按排序号排序）
     */

    @Override
    public List<DataValue> findEnabledDataValueByEntryId(Long dataEntryId) {
        Assert.notNull(dataEntryId, "entryId不能为null");
        List<DataValue> dataValues = dataValueDAO
                .getEnabledDataValueByEntryId(dataEntryId);

        lineUpDataValue(dataValues);
        return dataValues;
    }

    /**
     * 根据词条id和数据值的key查询数据值
     * 
     * @param entryId
     *            不能为null
     * @param key
     *            不能为null
     * @return 返回根据词条id和数据值的key查询数据值，如果不存在返回null
     */
    @Override
    public DataValue findDataValueByEntryIdAndKey(Long dataEntryId, String key) {
        Assert.notNull(dataEntryId, "dataEntryId不能为null");
        Assert.notNull(key, "key不能为null");
        return dataValueDAO.getDataValueByEntryIdAndKey(dataEntryId, key);
    }

    /**
     * 添加数据值
     * 
     * @param dataValue
     *            不能为null ，dataValue.dataValueId必须为null
     * @throws BusinessException
     *             ,当同一词条下的dataValue.value重复或dataValue.key重复时
     */
    @Override
    public void addDataValue(DataValue dataValue, Long toId)
            throws BusinessException {
        Assert.notNull(dataValue, "dataValue不能为null");
        Assert.isNull(dataValue.getDataValueId(), "dataValueId必须为null");
        List<DataValue> dataValues = dataValueDAO.getSameValueOrKeyByEntryId(
                dataValue.getValue(), dataValue.getKey(), dataValue
                        .getDataEntry().getEntryId());
        if (dataValues.size() == 0) {
            if (toId == null) {
                List<DataValue> dvs = ((DataEntry) dataEntryDAO.get(dataValue
                        .getDataEntry().getEntryId())).getDataValues();
                if (dvs == null || dvs.size() == 0) {
                    dataValue.setOrderIndex(1);
                } else {
                    dataValue.setOrderIndex(dvs.size() + 1);
                }
            } else {
                DataValue toDataValue = dataValueDAO.get(toId);
                if(toDataValue==null){
                	throw new ConcurrencyException("选中的数据值已被别人删除，请刷新读取最新数据",
                    "JC_DD_C_1"); 
                }
                int toOrderIndex = toDataValue.getOrderIndex();

                List<DataValue> needChangeDV = dataValueDAO
                        .getDataValueByIndexNotLessThanToId(toOrderIndex,
                                dataValue.getDataEntry().getEntryId());

                for (DataValue dv : needChangeDV) {
                    dv.setOrderIndex(dv.getOrderIndex() + 1);
                    dataValueDAO.update(dv);
                }
                dataValue.setOrderIndex(toOrderIndex);
            }
            dataValueDAO.save(dataValue);
        } else {
            throw new BusinessException("重复的key或值", "JC2_DD_B_1");
        }
    }

    /**
     * 修改数据值
     * 
     * @param dataValue
     *            不能为null ，dataValue.dataValueId不能为null
     * @throws BusinessException
     *             ,当同一词条下的dataValue.value重复或dataValue.key重复时
     */
    @Override
    public void updateDataValue(DataValue dataValue) throws BusinessException {
        Assert.notNull(dataValue, "dataValue不能为null");
        Assert.notNull(dataValue.getDataValueId(), "dataValueId不能为null");
        DataValue dv = dataValueDAO.get(dataValue.getDataValueId());
        if(dv==null){
        	throw new ConcurrencyException("该数据值之前已被别人删除，请刷新读取最新数据",
            "JC_DD_C_1");
        }
        
        List<DataValue> dataValues = dataValueDAO
                .getSameValueOrKeyByEntryIdExceptByDataValueId(dataValue
                        .getValue(), dataValue.getKey(), dataValue
                        .getDataEntry().getEntryId(), dataValue
                        .getDataValueId());
        if (dataValues.size() > 0) {
            throw new BusinessException("重复的key或值", "JC2_DD_B_1");
        } else {
            dataEntryDAO.clearEntityOnSession(dataValue.getDataEntry());
            dataValueDAO.update(dataValue);
        }
    }

    /**
     * 删除数据值
     * 
     * @param dataValueId
     *            不能为null;
     * @param version
     *            不能为null
     * @throws BusinessException
     *             ，当有外键引用此值时
     */
    @Override
    public void removeDataValue(Long dataValueId, Long version)
            throws BusinessException, ConcurrencyException {
        Assert.notNull(dataValueId, "dataValueId不能为null");
        Assert.notNull(version, "version不能为null");

        DataValue dv = dataValueDAO.get(dataValueId);
        if (dv == null) {
            throw new ConcurrencyException("该数据值之前已被别人删除，请刷新读取最新数据",
                    "JC_DD_C_1");
        }

        dataValueDAO.deleteDataValueByIdAndVersion(dataValueId, version);
        List<DataValue> dvs = dataValueDAO.getDataValueByIndexNotLessThanToId(
                dv.getOrderIndex(), dv.getDataEntry().getEntryId());
        if (dvs != null) {
            for (DataValue needChangeDV : dvs) {
                needChangeDV.setOrderIndex(needChangeDV.getOrderIndex() - 1);
                dataValueDAO.update(needChangeDV);
            }
        }
    }

    @Override
    public DataValue findDataValueByEntryNameAndKey(String entryName, String key) {
        Assert.notNull(entryName, "entryName不能为null");
        Assert.notNull(key, "key不能为null");
        return dataValueDAO.getDataValueByEntryNameAndKey(entryName, key);
    }

    @Override
    public List<DataValue> findEnabledDataValueByEntryName(String entryName) {
        Assert.notNull(entryName, "entryName不能为null");
        List<DataValue> dataValues = dataValueDAO
                .getEnabledDataValueByEntryName(entryName);
        if (dataValues == null || dataValues.size() == 0) {
            return null;
        }
        lineUpDataValue(dataValues);
        return dataValues;
    }

    @Override
    public void removeDataValue(DataValue dataValue) throws BusinessException {
        Assert.notNull(dataValue, "dataValue不能为null");
        dataValueDAO.delete(dataValue);
        List<DataValue> dvs = dataValueDAO.getDataValueByIndexNotLessThanToId(
                dataValue.getOrderIndex(), dataValue.getDataEntry()
                        .getEntryId());
        if (dvs != null) {
            for (DataValue needChangeDV : dvs) {
                needChangeDV.setOrderIndex(needChangeDV.getOrderIndex() - 1);
                dataValueDAO.update(needChangeDV);
            }
        }
    }

    @Override
    public void moveDataValue(Long fromId, Long toId, Long entryId) {
        Assert.notNull(fromId, "fromId不能为null!");
        Assert.notNull(entryId, "entryId不能为null");
        DataValue dataValueFrom = dataValueDAO.get(fromId);
        // 移动到最上面, 当第二个参数为null时
        if (toId == null) {
            if (dataValueFrom != null) {
                List<DataValue> list = new ArrayList<DataValue>();
                list = dataValueDAO.getDataValueByIndexNotLessThanToId(
                        dataValueFrom.getOrderIndex(), entryId);
                if (list != null) {
                    for (DataValue d : list) {
                        d.setOrderIndex(d.getOrderIndex() - 1);
                        dataValueDAO.update(d);
                    }
                    dataValueFrom.setOrderIndex(dataValueFrom.getOrderIndex()
                            + list.size());
                }
                dataValueDAO.update(dataValueFrom);
            }

        } else {
            // 数据向上移动
            DataValue dataValueTo = dataValueDAO.get(toId);
            if (dataValueFrom.getOrderIndex() < dataValueTo.getOrderIndex()) {

                Integer newOrderIndex;
                if (dataValueTo != null && dataValueFrom != null) {
                    List<DataValue> list = new ArrayList<DataValue>();
                    list = dataValueDAO.getDataValueBetweenIdMoveUp(
                            dataValueFrom.getOrderIndex(), dataValueTo
                                    .getOrderIndex(), entryId);
                    newOrderIndex = dataValueTo.getOrderIndex() - 1;
                    if (list != null) {
                        for (DataValue d : list) {
                            d.setOrderIndex(d.getOrderIndex() - 1);
                            dataValueDAO.update(d);
                        }
                        dataValueFrom.setOrderIndex(newOrderIndex);
                        dataValueDAO.update(dataValueFrom);
                    }
                }
            }
            // 数据值向下移动
            if (dataValueFrom.getOrderIndex() > dataValueTo.getOrderIndex()) {
                Integer newOrderIndex;
                if (dataValueTo != null && dataValueFrom != null) {
                    List<DataValue> list = new ArrayList<DataValue>();
                    list = dataValueDAO.getDataValueBetweenIdMoveDown(
                            dataValueFrom.getOrderIndex(), dataValueTo
                                    .getOrderIndex(), entryId);
                    newOrderIndex = dataValueTo.getOrderIndex();
                    if (list != null) {
                        for (DataValue d : list) {
                            d.setOrderIndex(d.getOrderIndex() + 1);
                            dataValueDAO.update(d);
                        }
                        dataValueFrom.setOrderIndex(newOrderIndex);
                        dataValueDAO.update(dataValueFrom);
                    }
                }
            }
        }

    }

    /** 对根节点的字集合进行排序 */
    private void lineUpDataValue(List<DataValue> dataValues) {
        if (dataValues.size() == 0) {
            return;
        } else {
            Collections.sort(dataValues, new LineUpCondition());
        }
    }

    /** 该类给出排序条件 -1 0 1 */
    private class LineUpCondition implements Comparator<DataValue> {

        @Override
        public int compare(DataValue d1, DataValue d2) {
            return Integer.valueOf(d2.getOrderIndex()).compareTo(
                    Integer.valueOf(d1.getOrderIndex()));
        }

    }
}

// /:~
